package org.i0o.webplus.commons.util.populator.converters;

import java.util.Calendar;
import java.util.Date;

import org.i0o.webplus.commons.util.populator.exception.ConversionException;

/**
 * 数值类型Converter
 * 
 * @author <a href="mailto:781131@gmail.com">HTF</a>
 * @version 2010-5-27
 */
public abstract class NumberConverter extends BaseConverter
	 {

	/*
	 * (non-Javadoc)
	 * @see
	 * com.citinet.webplus.util.populator.converters.BaseConverter#convertToType
	 * (java.lang.Object, java.lang.Class)
	 */
	@Override
	protected Object convertToType(Object value, Class<?> targetType, Object... configs) {
		if (value instanceof Number) {
			return this.toNumber((Number) value, targetType);
		}

		// Date
		if (value instanceof Date) {
			return new Long(((Date) value).getTime());
		}

		// Calendar
		if (value instanceof Calendar) {
			return new Long(((Calendar) value).getTime().getTime());
		}

		String stringValue = value.toString().trim();
		Number number = null;
		if (stringValue.length() == 0) {
			return null;
		} else {
			number = this.toNumber(stringValue, targetType);
		}

		return this.toNumber(number, targetType);
	}

	/**
	 * 将字符串对象进行转换
	 * 
	 * @param value
	 * @param targetType
	 * @return
	 */
	private Number toNumber(String value, Class<?> targetType) {
		if (targetType.equals(Byte.class)||targetType.equals(Byte.TYPE)) {
			return new Byte(value);
		}

		if (targetType.equals(Short.class)||targetType.equals(Short.TYPE)) {
			return new Short(value);
		}

		if (targetType.equals(Integer.class)||targetType.equals(Integer.TYPE)) {
			return new Integer(value);
		}

		if (targetType.equals(Long.class)||targetType.equals(Long.TYPE)) {
			return new Long(value);
		}

		if (targetType.equals(Float.class)||targetType.equals(Float.TYPE)) {
			return new Float(value);
		}

		if (targetType.equals(Double.class)||targetType.equals(Double.TYPE)) {
			return new Double(value);
		}
		throw new ConversionException("Cannot conversion");
	}

	/**
	 * 转换所有Number类型
	 * 
	 * @param value
	 * @param targetType
	 * @return
	 */
	private Number toNumber(Number value, Class<?> targetType) {
		if (targetType.equals(value.getClass())) {
			return value;
		}
		// Byte
		if (targetType.equals(Byte.class)) {
			if (value.longValue() > Byte.MAX_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too large" + targetType.toString());
			}
			if (value.longValue() < Byte.MIN_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too small" + targetType.toString());
			}
			return new Byte(value.byteValue());
		}

		// Short
		if (targetType.equals(Short.class) || targetType.equals(Short.TYPE)) {
			if (value.longValue() > Short.MAX_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too large" + targetType.toString());
			}
			if (value.longValue() < Short.MIN_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too small" + targetType.toString());
			}
			return new Short(value.shortValue());
		}

		// Integer
		if (targetType.equals(Integer.class) || targetType.equals(Integer.TYPE)) {
			if (value.longValue() > Integer.MAX_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too large" + targetType.toString());
			}
			if (value.longValue() < Integer.MIN_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too small" + targetType.toString());
			}
			return new Integer(value.intValue());
		}

		// Long
		if (targetType.equals(Long.class) || targetType.equals(Integer.TYPE)) {
			if (value.longValue() > Long.MAX_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too large" + targetType.toString());
			}
			if (value.longValue() < Long.MIN_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too small" + targetType.toString());
			}
			return new Long(value.longValue());
		}

		// Float
		if (targetType.equals(Float.class) || targetType.equals(Float.TYPE)) {
			if (value.longValue() > Float.MAX_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too large" + targetType.toString());
			}
			if (value.longValue() < Float.MIN_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too small" + targetType.toString());
			}
			return new Float(value.floatValue());
		}

		// Double
		if (targetType.equals(Double.class) || targetType.equals(Double.TYPE)) {
			if (value.longValue() > Double.MAX_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too large" + targetType.toString());
			}
			if (value.longValue() < Double.MIN_VALUE) {
				throw new ConversionException(value.getClass().toString() + " value " + value + " is too small" + targetType.toString());
			}
			return new Double(value.doubleValue());
		}

		throw new ConversionException("Cannot conversion");
	}

}
